return {
    {
        "hrsh7th/nvim-cmp",
        enabled = true,
        dependencies = {
            "hrsh7th/cmp-nvim-lsp",
            "hrsh7th/cmp-buffer",
            "hrsh7th/cmp-path",
            "hrsh7th/cmp-cmdline",
        },
        event = "InsertEnter",
        opts = function(_, opts)
            local cmp = require("cmp")
            opts.mapping = cmp.mapping.preset.insert({
                ["<Tab>"] = cmp.mapping(function(fallback)
                    if cmp.visible() then
                        cmp.select_next_item()
                    else
                        fallback()
                    end
                end, { "i", "s" }),
                ["<S-Tab>"] = cmp.mapping(function(fallback)
                    if cmp.visible() then
                        cmp.select_prev_item()
                    else
                        fallback()
                    end
                end, { "i", "s" }),
                ["<C-d>"] = cmp.mapping.scroll_docs(-4),
                ["<C-f>"] = cmp.mapping.scroll_docs(4),
                ["<C-n>"] = cmp.mapping.complete(),
                ["<CR>"] = cmp.mapping.confirm({ select = true }),
            })
            opts.snippet = {
                expand = function(args)
                    local luasnip, ok = pcall(require, "luasnip")
                    if ok then
                        luasnip.lsp_expand(args.body)
                    else
                        -- 如果没有luasnip，使用简单的文本替换
                        -- vim.api.nvim_put({ args.body }, "c", true, true)
                        vim.snippet.expand(args.body) -- For native neovim snippets (Neovim v0.10+)
                    end
                end,
            }
            opts.window = {
                -- completion = cmp.config.window.bordered(),
                -- documentation = cmp.config.window.bordered(),
            }
            opts.sources = cmp.config.sources({
                { name = "nvim_lsp" },
                { name = "vsnip" }, -- For vsnip users.
                -- { name = 'luasnip' }, -- For luasnip users.
                -- { name = 'snippy' }, -- For snippy users.
                -- { name = 'ultisnips' }, -- For ultisnips users.
            }, {
                { name = "buffer" },
            })
            opts.formatting = {
                format = function(entry, vim_item)
                    -- 设置来源图标
                    local icons = {
                        nvim_lsp = "",
                        luasnip = "",
                        buffer = "",
                        path = "",
                        cmdline = "",
                    }
                    vim_item.kind = string.format("%s %s", icons[entry.source.name] or "", vim_item.kind)
                    return vim_item
                end,
            }
            opts.experimental = {
                ghost_text = true,
            }
        end,
        config = function(_, opts)
            local cmp = require("cmp")
            cmp.setup(opts)
            -- 命令行自动补全
            cmp.setup.cmdline(":", {
                mapping = cmp.mapping.preset.cmdline(),
                sources = cmp.config.sources({
                    { name = "path" },
                }, {
                    { name = "cmdline" },
                }),
            })

            -- 搜索自动补全
            cmp.setup.cmdline("/", {
                mapping = cmp.mapping.preset.cmdline(),
                sources = {
                    { name = "buffer" },
                },
            })

            -- Setup lspconfig.
            local capabilities = require("cmp_nvim_lsp").default_capabilities()
            vim.lsp.config("pyright", {
                capabilities = capabilities,
            })
            vim.lsp.enable("pyright")
        end,
    },
}
